class MyPlugin {
  // webpack 插件是一个具有 apply 属性的 JavaScript 对象。
  // apply 属性会被 webpack compiler 调用，并且 compiler 对象可在整个编译生命周期访问(其中还有各种hook提供调用)。
  constructor(obj) {
    console.log(obj); // 传进来的参数
  }

  apply(compiler) {
    // 'shouldEmit', // 此时返回 true/false
    // 'done', // 编译(compilation)完成
    // 'additionalPass',
    // 'beforeRun', // compiler.run() 执行之前，添加一个钩子
    // 'run', // 开始读取 records 之前，钩入(hook into) compiler
    // 'emit', // 生成资源到 output 目录之前
    // 'assetEmitted', //在 asset 被输出时执行。此钩子可以访问被输出的 asset 的相关信息，例如它的输出路径和字节内容。
    // 'afterEmit', // 生成资源到 output 目录之后
    // 'thisCompilation', // 触发 compilation 事件之前执行（查看下面的 compilation）
    // 'compilation', // 编译(compilation)创建之后，执行插件
    // 'normalModuleFactory', // NormalModuleFactory 创建之后，执行插件
    // 'contextModuleFactory', // ContextModuleFactory 创建之后，执行插件
    // 'beforeCompile', // 编译(compilation)参数创建之后，执行插件
    // 'compile', // 一个新的编译(compilation)创建之后，钩入(hook into) compiler
    // 'make', // compilation 结束之前执行
    // 'afterCompile', //compilation 结束和封印之后执行
    // 'watchRun', // 监听模式下，一个新的编译(compilation)触发之后，执行一个插件，但是是在实际编译开始之前
    // 'failed', // 编译(compilation)失败
    // 'invalid', // 监听模式下，编译无效时
    // 'watchClose', // 监听模式停止
    // 'environment', // environment 准备好之后，执行插件
    // 'afterEnvironment', // environment 安装完成之后，执行插件
    // 'afterPlugins', // 设置完初始插件之后，执行插件。
    // 'afterResolvers', // resolver 安装完成之后，执行插件
    // 'entryOption', // 在 entry 配置项处理过之后，执行插件
    // console.log('插件被调用了。apply的钩子：', Object.keys(compiler.hooks))
    compiler.hooks.run.tap('MyPlugin', (params) => {
      console.log('以同步方式触及 compile 钩子。');
    });
    compiler.hooks.run.tapAsync('MyPlugin', (compiler, callback) => {
      console.log('以异步方式触及 run 钩子。');
      callback();
    });
    compiler.hooks.run.tapPromise('MyPlugin', (compiler) => {
      return new Promise((resolve) => setTimeout(resolve, 1000)).then(() => {
        console.log('以具有延迟的异步方式触及 run 钩子');
      });
    });
  }
}

module.exports = MyPlugin;
